package com.atguigu.paymentdemo.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConfig;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.domain.GoodsDetail;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.atguigu.paymentdemo.entity.*;
import com.atguigu.paymentdemo.enums.OrderStatus;
import com.atguigu.paymentdemo.enums.PayType;
import com.atguigu.paymentdemo.enums.wxpay.AliPayTradeState;
import com.atguigu.paymentdemo.mapper.OrderInfoMapper;
import com.atguigu.paymentdemo.service.AliPayService;
import com.atguigu.paymentdemo.service.OrderInfoService;
import com.atguigu.paymentdemo.service.PaymentInfoService;
import com.atguigu.paymentdemo.service.RefundInfoService;
import com.atguigu.paymentdemo.util.*;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.google.gson.Gson;
import com.google.gson.internal.LinkedTreeMap;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;

import static com.atguigu.paymentdemo.controller.AliPayController.times;

@Service
@Slf4j
public class AliPayServiceImpl implements AliPayService {

    @Resource
    private OrderInfoService orderInfoService;

    @Resource
    private AlipayClient alipayClient;

    @Resource
    private Environment config;

    @Resource
    private PaymentInfoService paymentInfoService;

    @Resource
    private RefundInfoService refundsInfoService;
    @Autowired
    private OrderInfoMapper orderInfoMapper;
    private final ReentrantLock lock = new ReentrantLock();
    DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String tradeCreate(Long productId) {

        try {
            //生成订单
            log.info("生成订单");
            OrderInfo orderInfo = orderInfoService.createOrderByProductId(productId, PayType.ALIPAY.getType());

            //调用支付宝接口
            AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
            //配置需要的公共请求参数
            //支付完成后，支付宝向谷粒学院发起异步通知的地址
            request.setNotifyUrl(config.getProperty("alipay.notify-url"));
            //支付完成后，我们想让页面跳转回谷粒学院的页面，配置returnUrl
            request.setReturnUrl(config.getProperty("alipay.return-url"));

            //组装当前业务方法的请求参数
            JSONObject bizContent = new JSONObject();
            bizContent.put("out_trade_no", orderInfo.getOrderNo());
            BigDecimal total = new BigDecimal(orderInfo.getTotalFee().toString()).divide(new BigDecimal("100"));
            bizContent.put("total_amount", total);
            bizContent.put("subject", orderInfo.getTitle());
            bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");

            request.setBizContent(bizContent.toString());
            log.info("请求支付宝的参数"+JSONObject.toJSONString(request));
            //执行请求，调用支付宝接口
            AlipayTradePagePayResponse response = alipayClient.pageExecute(request);

            if(response.isSuccess()){
                log.info("调用成功，返回结果 ===> " + response.getBody());
                return response.getBody();
            } else {
                log.info("调用失败，返回码 ===> " + response.getCode() + ", 返回描述 ===> " + response.getMsg());
                throw new RuntimeException("创建支付交易失败");
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
            throw new RuntimeException("创建支付交易失败");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String tradeWapCreate(CatOutEntity catOutEntity) {
        AlipayTradeWapPayResponse response = null;

        try {
//            getAlipayConfigRandom();
//            AlipayTradeWapPay alipay=new AlipayTradeWapPay();
            AlipayConfig cfgRandom= this.getAlipayConfigRandom();
            log.info("cfgRandom:{}",JSONObject.toJSONString(cfgRandom));
            // 初始化SDK
//            AlipayClient alipayClient = new DefaultAlipayClient(AlipayTradeWapPay.getAlipayConfig());
            AlipayClient alipayClient = new DefaultAlipayClient(cfgRandom);

            // 构造请求参数以调用接口
            AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
            AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();



            //生成订单
            OrderInfo orderInfo = orderInfoService.createOrderByProductId2(catOutEntity.getProductId(), PayType.ALIPAY.getType(),catOutEntity);

            //组装当前业务方法的请求参数
//            JSONObject bizContent = new JSONObject();
//            bizContent.put("out_trade_no", orderInfo.getOrderNo());
//            BigDecimal total = new BigDecimal(orderInfo.getTotalFee().toString()).divide(new BigDecimal("100"));
//            bizContent.put("total_amount", total);
//            bizContent.put("subject", orderInfo.getTitle());
//            bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");
//
//            request.setBizContent(bizContent.toString());
//            log.info("请求支付宝的参数"+JSONObject.toJSONString(request));

            // 设置订单总金额
            model.setTotalAmount(orderInfo.getTotalFee().toString());

            // 设置订单标题
            model.setSubject(orderInfo.getTitle());

            // 设置产品码
            model.setProductCode("QUICK_WAP_WAY");

            // 设置针对用户授权接口
            model.setAuthToken("appopenBb64d181d0146481ab6a762c00714cC27");

            // 设置用户付款中途退出返回商户网站的地址
            model.setQuitUrl("https://www.53lmc.com");

            // 设置订单包含的商品列表信息
            List<GoodsDetail> goodsDetail = new ArrayList<GoodsDetail>();
            GoodsDetail goodsDetail0 = new GoodsDetail();
            goodsDetail0.setGoodsName(orderInfo.getTitle());
            goodsDetail0.setAlipayGoodsId(catOutEntity.getProductId().toString());
            goodsDetail0.setQuantity(1L);
            goodsDetail0.setPrice(orderInfo.getTotalFee().toString());
            goodsDetail0.setGoodsId("apple-01");
            goodsDetail0.setGoodsCategory("34543238");
            goodsDetail0.setCategoriesTree("124868003|126232002|126252004");
            goodsDetail0.setBody(orderInfo.getTitle());
            goodsDetail0.setShowUrl("http://www.alipay.com/xxx.jpg");
            goodsDetail.add(goodsDetail0);
            model.setGoodsDetail(goodsDetail);

            // 设置订单绝对超时时间
            Date timeExpire = new Date();
            // 设置订单绝对超时时间 为半小时
            timeExpire.setTime(System.currentTimeMillis() + 1000 * 60 * 30);

            model.setTimeExpire(df.format(timeExpire));



            // 设置商户传入业务信息
            model.setBusinessParams("{\"mc_create_trade_ip\":\"127.0.0.1\"}");

            // 设置公用回传参数
            model.setPassbackParams("merchantBizType%3d3C%26merchantBizNo%3d2016010101111");

            // 设置商户的原始订单号
            model.setMerchantOrderNo("20161008001");
            model.setOutTradeNo(orderInfo.getOrderNo());
            model.setTotalAmount(orderInfo.getTotalFee().toString());

            request.setBizModel(model);
            //支付完成后，支付宝向谷粒学院发起异步通知的地址
            request.setNotifyUrl(config.getProperty("alipay.notify-url"));

            //支付完成后，我们想让页面跳转回谷粒学院的页面，配置returnUrl
            request.setReturnUrl(config.getProperty("alipay.return-url"));
            // 第三方代调用模式下请设置app_auth_token
            // request.putOtherTextParam("app_auth_token", "<-- 请填写应用授权令牌 -->");
            log.info("请求支付宝支付request参数为:{}",JSONObject.toJSONString(request));
            response = alipayClient.pageExecute(request, "POST");
            // 如果需要返回GET请求，请使用
            // AlipayTradeWapPayResponse response = alipayClient.pageExecute(request, "GET");
            String pageRedirectionData = response.getBody();
            System.out.println(pageRedirectionData);

            if (response.isSuccess()) {
                System.out.println("调用成功");
                return response.getBody();
            } else {
                System.out.println("调用失败");
                // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
                // String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
                // System.out.println(diagnosisUrl);
                log.info("调用失败，返回码 ===> " + response.getCode() + ", 返回描述 ===> " + response.getMsg());
                throw new RuntimeException("创建支付交易失败");
            }
        } catch (AlipayApiException e) {
            log.info("调用失败，返回码 ===> " + response.getCode() + ", 返回描述 ===> " + response.getMsg());
            throw new RuntimeException("创建支付交易失败");
        }

    }

    /*
     * ys支付请求
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String tradeWapCreate2(CatOutEntity catOutEntity) {

        try {


            // 构造请求参数以调用接口
            AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
            AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();


            //生成订单
            OrderInfo orderInfo = orderInfoService.createOrderByProductId2(catOutEntity.getProductId(), PayType.ALIPAY.getType(),catOutEntity);

            String responseStr= sendYsPay(catOutEntity,orderInfo);
            log.info("ys支付响应结果:"+responseStr);

            JSONObject jsonObject= JSON.parseObject(responseStr);
            String resultCode =jsonObject.getString("code");

            if (resultCode.equals("200")) {
//                System.out.println("调用成功");
                log.info("返回码 ===> " + resultCode + ", 返回描述 ===> " + "调用成功");
                return responseStr;
            } else {
                System.out.println("调用失败");

                log.info("调用失败，返回码 ===> " + resultCode + ", 返回描述 ===> " + responseStr);
                throw new RuntimeException("创建支付交易失败");
            }
        } catch (Exception e) {
            log.error("ys支付失败"+e.getMessage());
            throw new RuntimeException("创建支付交易失败");
        }

    }


    /**
     * 处理订单
     * @param params
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void processOrder(Map<String, String> params) {

        log.info("处理订单");

        //获取订单号
        String orderNo = params.get("out_trade_no");


        /*在对业务数据进行状态检查和处理之前，
        要采用数据锁进行并发控制，
        以避免函数重入造成的数据混乱*/
        //尝试获取锁：
        // 成功获取则立即返回true，获取失败则立即返回false。不必一直等待锁的释放
        if(lock.tryLock()) {
            try {

                //处理重复通知
                //接口调用的幂等性：无论接口被调用多少次，以下业务执行一次
                OrderInfo orderInfo=orderInfoService.getOrderByOrderNo(orderNo);
                log.info("处理重复通知，订单号相关数据 ===> " + JSONObject.toJSONString(orderInfo));
                String orderStatus = orderInfo.getOrderStatus(); //订单状态
                String bxmId=orderInfo.getBxmId(); //变现猫id
                Long productId=orderInfo.getProductId(); //产品id
//                String orderStatus = orderInfoService.getOrderStatus(orderNo);
                if (!OrderStatus.NOTPAY.getType().equals(orderStatus)) {
                    log.info("重复通知，订单号 ===> " + orderNo);
                    return;
                }
                if(null!=bxmId && !bxmId.equals("0")){
                    log.info("变现猫id不为空，开始时间 ===> {}",df.format(new Date()));
                    times=times+1;
                    log.info("当前第{}次",times);
                    int klTimes=orderInfoMapper.getKlTimes();
                    if(times%klTimes==0){
                        log.info("跳过第{}次",times);
                    }else {
                        //向变现猫发送转化请求
                        String bxmResult= OkHttpGetRequest.okhttpGet(bxmId);
                        log.info("变现猫返回结果 bxmResult ===> {}", bxmResult);
                    }

                }

                //更新订单状态
                orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.SUCCESS);

//
                if(orderNo.startsWith("QYC")){
                    log.info("新增权益卡,开始时间 ===> {}",df.format(new Date()));
                    CatOutEntity catOutEntity= new CatOutEntity();
//                    catOutEntity.setId(IdWorker.getId());
                    catOutEntity.setBxm_id(bxmId);
                    catOutEntity.setPhone(orderInfo.getPhone());
                    catOutEntity.setCreateTime(new Date()    );
                    catOutEntity.setUpdateTime(new Date()    );
                    catOutEntity.setStatus("1");//已同步变现猫
                    catOutEntity.setNum(1);
                    orderInfoMapper.updateCardInfo(catOutEntity);
                    SendSms.sendTxSMS(orderInfo.getPhone(),"");
                }

                //记录支付日志
                paymentInfoService.createPaymentInfoForAliPay(params);

            } finally {
                //要主动释放锁
                lock.unlock();
            }
        }

    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void processOrder2(Map<String, String> params) {

        log.info("处理订单");

        //获取订单号
        String orderNo = params.get("mchOrderNo");


        /*在对业务数据进行状态检查和处理之前，
        要采用数据锁进行并发控制，
        以避免函数重入造成的数据混乱*/
        //尝试获取锁：
        // 成功获取则立即返回true，获取失败则立即返回false。不必一直等待锁的释放
        if(lock.tryLock()) {
            try {

                //处理重复通知
                //接口调用的幂等性：无论接口被调用多少次，以下业务执行一次
                OrderInfo orderInfo=orderInfoService.getOrderByOrderNo(orderNo);
                log.info("处理重复通知，订单号相关数据 ===> " + JSONObject.toJSONString(orderInfo));
                String orderStatus = orderInfo.getOrderStatus(); //订单状态
                String bxmId=orderInfo.getBxmId(); //变现猫id
                Long productId=orderInfo.getProductId(); //产品id
//                String orderStatus = orderInfoService.getOrderStatus(orderNo);
                if (!OrderStatus.NOTPAY.getType().equals(orderStatus)) {
                    log.info("重复通知，订单号 ===> " + orderNo);
                    return;
                }
                if(null!=bxmId && !bxmId.equals("0")){
                    log.info("变现猫id不为空，开始时间 ===> {}",df.format(new Date()));
                    times=times+1;
                    log.info("当前第{}次",times);
                    int klTimes=orderInfoMapper.getKlTimes();
                    if(times%klTimes==0){
                        log.info("跳过第{}次",times);
                    }else {
                        //向变现猫发送转化请求
                        String bxmResult= OkHttpGetRequest.okhttpGet(bxmId);
                        log.info("变现猫返回结果 bxmResult ===> {}", bxmResult);
                    }

                }

                //更新订单状态
                orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.SUCCESS);

//
                if(orderNo.startsWith("QYC")){
                    log.info("新增权益卡,开始时间 ===> {}",df.format(new Date()));
                    CatOutEntity catOutEntity= new CatOutEntity();
//                    catOutEntity.setId(IdWorker.getId());
                    catOutEntity.setBxm_id(bxmId);
                    catOutEntity.setPhone(orderInfo.getPhone());
                    catOutEntity.setCreateTime(new Date()    );
                    catOutEntity.setUpdateTime(new Date()    );
                    catOutEntity.setStatus("1");//已同步变现猫
                    catOutEntity.setNum(1);
                    orderInfoMapper.updateCardInfo(catOutEntity);
                    SendSms.sendTxSMS(orderInfo.getPhone(),"");
                }

                //记录支付日志
                paymentInfoService.createPaymentInfoForYsPay(params);

            } finally {
                //要主动释放锁
                lock.unlock();
            }
        }

    }


    /**
     * 用户取消订单
     * @param orderNo
     */
    @Override
    public void cancelOrder(String orderNo) {

        //调用支付宝提供的统一收单交易关闭接口
        this.closeOrder(orderNo);

        //更新用户订单状态
        orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.CANCEL);
    }

    /**
     * 查询订单
     * @param orderNo
     * @return 返回订单查询结果，如果返回null则表示支付宝端尚未创建订单
     */
    @Override
    public String queryOrder(String orderNo) {

        try {
            log.info("查单接口调用 ===> {}", orderNo);

            AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
            JSONObject bizContent = new JSONObject();
            bizContent.put("out_trade_no", orderNo);
            request.setBizContent(bizContent.toString());

            AlipayTradeQueryResponse response = alipayClient.execute(request);
            if(response.isSuccess()){
                log.info("调用成功，返回结果 ===> " + response.getBody());
                return response.getBody();
            } else {
                log.info("调用失败，返回码 ===> " + response.getCode() + ", 返回描述 ===> " + response.getMsg());
                //throw new RuntimeException("查单接口的调用失败");
                return null;//订单不存在
            }

        } catch (AlipayApiException e) {
            e.printStackTrace();
            throw new RuntimeException("查单接口的调用失败");
        }
    }

    /**
     * 根据订单号调用支付宝查单接口，核实订单状态
     * 如果订单未创建，则更新商户端订单状态
     * 如果订单未支付，则调用关单接口关闭订单，并更新商户端订单状态
     * 如果订单已支付，则更新商户端订单状态，并记录支付日志
     * @param orderNo
     */
    @Override
    public void checkOrderStatus(String orderNo) {

        log.warn("根据订单号核实订单状态 ===> {}", orderNo);

        String result = this.queryOrder(orderNo);

        //订单未创建
        if(result == null){
            log.warn("核实订单未创建 ===> {}", orderNo);
            //更新本地订单状态
            orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.CLOSED);
        }

        //解析查单响应结果
        Gson gson = new Gson();
        HashMap<String, LinkedTreeMap> resultMap = gson.fromJson(result, HashMap.class);
        LinkedTreeMap alipayTradeQueryResponse = resultMap.get("alipay_trade_query_response");

        String tradeStatus = (String)alipayTradeQueryResponse.get("trade_status");
        if(AliPayTradeState.NOTPAY.getType().equals(tradeStatus)){
            log.warn("核实订单未支付 ===> {}", orderNo);

            //如果订单未支付，则调用关单接口关闭订单
            this.closeOrder(orderNo);

            // 并更新商户端订单状态
            orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.CLOSED);
        }

        if(AliPayTradeState.SUCCESS.getType().equals(tradeStatus)){
            log.warn("核实订单已支付 ===> {}", orderNo);

            //如果订单已支付，则更新商户端订单状态
            orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.SUCCESS);

            //并记录支付日志
            paymentInfoService.createPaymentInfoForAliPay(alipayTradeQueryResponse);
        }

    }

    /**
     * 关单接口的调用
     * @param orderNo 订单号
     */
    private void closeOrder(String orderNo) {

        try {
            log.info("关单接口的调用，订单号 ===> {}", orderNo);

            AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
            JSONObject bizContent = new JSONObject();
            bizContent.put("out_trade_no", orderNo);
            request.setBizContent(bizContent.toString());
            AlipayTradeCloseResponse response = alipayClient.execute(request);

            if(response.isSuccess()){
                log.info("调用成功，返回结果 ===> " + response.getBody());
            } else {
                log.info("调用失败，返回码 ===> " + response.getCode() + ", 返回描述 ===> " + response.getMsg());
                //throw new RuntimeException("关单接口的调用失败");
            }

        } catch (AlipayApiException e) {
            e.printStackTrace();
            throw new RuntimeException("关单接口的调用失败");
        }
    }

    /**
     * 退款
     * @param orderNo
     * @param reason
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void refund(String orderNo, String reason) {

        try {
            log.info("调用退款API");

            //创建退款单
            RefundInfo refundInfo = refundsInfoService.createRefundByOrderNoForAliPay(orderNo, reason);

            //调用统一收单交易退款接口
            AlipayTradeRefundRequest request = new AlipayTradeRefundRequest ();

            //组装当前业务方法的请求参数
            JSONObject bizContent = new JSONObject();
            bizContent.put("out_trade_no", orderNo);//订单编号
            BigDecimal refund = new BigDecimal(refundInfo.getRefund().toString()).divide(new BigDecimal("100"));
            //BigDecimal refund = new BigDecimal("2").divide(new BigDecimal("100"));
            bizContent.put("refund_amount", refund);//退款金额：不能大于支付金额
            bizContent.put("refund_reason", reason);//退款原因(可选)

            request.setBizContent(bizContent.toString());

            //执行请求，调用支付宝接口
            AlipayTradeRefundResponse response = alipayClient.execute(request);

            if(response.isSuccess()){
                log.info("调用成功，返回结果 ===> " + response.getBody());

                //更新订单状态
                orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.REFUND_SUCCESS);

                //更新退款单
                refundsInfoService.updateRefundForAliPay(
                        refundInfo.getRefundNo(),
                        response.getBody(),
                        AliPayTradeState.REFUND_SUCCESS.getType()); //退款成功

            } else {
                log.info("调用失败，返回码 ===> " + response.getCode() + ", 返回描述 ===> " + response.getMsg());

                //更新订单状态
                orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.REFUND_ABNORMAL);

                //更新退款单
                refundsInfoService.updateRefundForAliPay(
                        refundInfo.getRefundNo(),
                        response.getBody(),
                        AliPayTradeState.REFUND_ERROR.getType()); //退款失败
            }


        } catch (AlipayApiException e) {
            e.printStackTrace();
            throw new RuntimeException("创建退款申请失败");
        }
    }

    /**
     * 查询退款
     * @param orderNo
     * @return
     */
    @Override
    public String queryRefund(String orderNo) {

        try {
            log.info("查询退款接口调用 ===> {}", orderNo);

            AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
            JSONObject bizContent = new JSONObject();
            bizContent.put("out_trade_no", orderNo);
            bizContent.put("out_request_no", orderNo);
            request.setBizContent(bizContent.toString());

            AlipayTradeFastpayRefundQueryResponse response = alipayClient.execute(request);
            if(response.isSuccess()){
                log.info("调用成功，返回结果 ===> " + response.getBody());
                return response.getBody();
            } else {
                log.info("调用失败，返回码 ===> " + response.getCode() + ", 返回描述 ===> " + response.getMsg());
                //throw new RuntimeException("查单接口的调用失败");
                return null;//订单不存在
            }

        } catch (AlipayApiException e) {
            e.printStackTrace();
            throw new RuntimeException("查单接口的调用失败");
        }
    }

    /**
     * 申请账单
     * @param billDate
     * @param type
     * @return
     */
    @Override
    public String queryBill(String billDate, String type) {

        try {

            AlipayDataDataserviceBillDownloadurlQueryRequest request = new AlipayDataDataserviceBillDownloadurlQueryRequest();
            JSONObject bizContent = new JSONObject();
            bizContent.put("bill_type", type);
            bizContent.put("bill_date", billDate);
            request.setBizContent(bizContent.toString());
            AlipayDataDataserviceBillDownloadurlQueryResponse response = alipayClient.execute(request);

            if(response.isSuccess()){
                log.info("调用成功，返回结果 ===> " + response.getBody());

                //获取账单下载地址
                Gson gson = new Gson();
                HashMap<String, LinkedTreeMap> resultMap = gson.fromJson(response.getBody(), HashMap.class);
                LinkedTreeMap billDownloadurlResponse = resultMap.get("alipay_data_dataservice_bill_downloadurl_query_response");
                String billDownloadUrl = (String)billDownloadurlResponse.get("bill_download_url");

                return billDownloadUrl;
            } else {
                log.info("调用失败，返回码 ===> " + response.getCode() + ", 返回描述 ===> " + response.getMsg());
                throw new RuntimeException("申请账单失败");
            }

        } catch (AlipayApiException e) {
            e.printStackTrace();
            throw new RuntimeException("申请账单失败");
        }
    }
    public void saveCatIn(String bxm_id){
        if(bxm_id==null||bxm_id.equals("0"   )){
            return;
        }
        Long startTime = System.currentTimeMillis();
//        log.info("saveCatIn id,开始时间 ===> {},{}", bxm_id,df.format(new Date()));
        CatInEntity catInEntity = new CatInEntity();
        catInEntity.setId(IdWorker.getId());
        catInEntity.setBxm_id(bxm_id);
        catInEntity.setCreateTime(new Date()    );
        catInEntity.setUpdateTime(new Date()    );
        orderInfoMapper.saveCatIn(catInEntity);
//        log.info("保存成功,cost time:{}ms",System.currentTimeMillis()-startTime);
    }
    public void saveCatOut(String bxm_id,String phone,String out_trade_no){
        if(bxm_id==null||bxm_id.equals("0"   )){
            return;
        }
        Long startTime = System.currentTimeMillis();
        log.info("catOutEntity id,开始时间 ===> {},{}", bxm_id,df.format(new Date()));
        CatOutEntity catOutEntity= new CatOutEntity();
        catOutEntity.setId(Long.parseLong(out_trade_no) );
        catOutEntity.setBxm_id(bxm_id);
        catOutEntity.setPhone(phone);
        catOutEntity.setCreateTime(new Date()    );
        catOutEntity.setUpdateTime(new Date()    );
        orderInfoMapper.saveCatOut(catOutEntity);
        log.info("保存成功,cost time:{}ms",System.currentTimeMillis()-startTime);
    }

    //充值
    public String phoneRecharge(CatOutEntity catOutEntity){
        String result="";
        try{
            //1. 查询是否购买100元权益卡
            log.info("1.检查权益卡信息是否可用 ===> {}", JSONObject.toJSONString(catOutEntity));
            catOutEntity.setProductId(12345L); //100元权益卡
            String phone=catOutEntity.getPhone();

            CatOutEntity cardInfo=orderInfoMapper.queryCardInfo(catOutEntity);
            if(cardInfo==null){
                return "权益卡已失效或没有购买权益卡";//权益卡已失效或没有购买权益卡
            }
            //权益卡可用次数减1
            if(cardInfo.getNum()<=0){
                cardInfo.setNum(0);
                log.info("可充值数量不足 ===> {}", phone);
                return "可充值数量不足";
            }else {
                cardInfo.setNum(cardInfo.getNum()-1);
                log.info("可充值数量-1 ===> {}", phone);
            }
            catOutEntity.setNum(cardInfo.getNum());
            catOutEntity.setStatus("0");//改为不可用状态
            catOutEntity.setUpdateTime(new Date()    );
            orderInfoMapper.updateCatOutNum(catOutEntity);

            //2.请求支付宝发起收费
            log.info("2.请求支付宝发起收费 ===> {}", JSONObject.toJSONString(catOutEntity));
            catOutEntity.setProductId(5L);// 设置付费的产品id 80元冲100元话费
            result=this.tradeWapCreate(catOutEntity);
            //3. 查询是否可以充值
//            log.info("2.查询是否可以充值 ===> {}", bxm_id);
//            phoneStatue=PhoneRechargeCheckUtil.telcheck(phone,"100");
            //3. 调用充值接口
//            if(phoneStatue.equals("0")){
//                PhoneRechargeUtil.recharge(phone,"100",bxm_id);
//            }
//            log.info("3.调用充值接口 ===> {}", bxm_id);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return result;
    }
    //充值
    public String phoneRecharge2(CatOutEntity catOutEntity){
        String result="";
        try{
            //1. 查询是否购买100元权益卡
            log.info("1.检查权益卡信息是否可用 ===> {}", JSONObject.toJSONString(catOutEntity));
            catOutEntity.setProductId(12345L); //100元权益卡
            String phone=catOutEntity.getPhone();

            CatOutEntity cardInfo=orderInfoMapper.queryCardInfo(catOutEntity);
            if(cardInfo==null){
                return "权益卡已失效或没有购买权益卡";//权益卡已失效或没有购买权益卡
            }
            //权益卡可用次数减1
            if(cardInfo.getNum()<=0){
                cardInfo.setNum(0);
                log.info("可充值数量不足 ===> {}", phone);
                return "可充值数量不足";
            }else {
                cardInfo.setNum(cardInfo.getNum()-1);
                log.info("可充值数量-1 ===> {}", phone);
            }
            catOutEntity.setNum(cardInfo.getNum());
            catOutEntity.setStatus("0");//改为不可用状态
            catOutEntity.setUpdateTime(new Date()    );
            orderInfoMapper.updateCatOutNum(catOutEntity);

            //2.请求支付宝发起收费
            log.info("2.请求支付宝发起收费 ===> {}", JSONObject.toJSONString(catOutEntity));
            catOutEntity.setProductId(5L);// 设置付费的产品id 80元冲100元话费
            result=this.tradeWapCreate2(catOutEntity);
            //3. 查询是否可以充值
//            log.info("2.查询是否可以充值 ===> {}", bxm_id);
//            phoneStatue=PhoneRechargeCheckUtil.telcheck(phone,"100");
            //3. 调用充值接口
//            if(phoneStatue.equals("0")){
//                PhoneRechargeUtil.recharge(phone,"100",bxm_id);
//            }
//            log.info("3.调用充值接口 ===> {}", bxm_id);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return result;
    }

    public void updateCatOut(String bxm_id,String phone){
        Long startTime = System.currentTimeMillis();
        log.info("updateCatOut id,开始时间 ===> {},{}", bxm_id,df.format(new Date()));
        CatOutEntity catOutEntity= new CatOutEntity();
        catOutEntity.setId(IdWorker.getId());
        catOutEntity.setBxm_id(bxm_id);
        catOutEntity.setPhone(phone);
        catOutEntity.setCreateTime(new Date()    );
        catOutEntity.setUpdateTime(new Date()    );
        catOutEntity.setStatus("1");//已同步变现猫
        orderInfoMapper.updateCatOut(catOutEntity);
        log.info("保存成功,cost time:{}ms",System.currentTimeMillis()-startTime);
    }
    public AlipayConfig getAlipayConfigRandom() {
        AlipayConfig alipayConfig = new AlipayConfig();
        List<UserInfoEntity> userInfoEntityList=orderInfoMapper.getUserInfoList();
        int num=userInfoEntityList.size();
        int index=new Random().nextInt(num);
        UserInfoEntity userInfoEntity=userInfoEntityList.get(index);
        alipayConfig.setServerUrl("https://openapi.alipay.com/gateway.do");
        alipayConfig.setAppId(userInfoEntity.getAppId());
        alipayConfig.setPrivateKey(userInfoEntity.getMerchantPrivateKey());
        alipayConfig.setFormat("json");
        alipayConfig.setAlipayPublicKey(userInfoEntity.getAlipayPublicKey());
        alipayConfig.setCharset("UTF-8");
        alipayConfig.setSignType("RSA2");
        return alipayConfig;
    }
    /*
     * ys支付参数设置，以及请求ys支付网关
     *
     */

    public String sendYsPay(CatOutEntity param,OrderInfo orderInfo){
        String payGateWay = "https://yishengzf-api.tszf66.com/api/v1/payment/init"; //支付网关
        String mchKey = "1315";//商户id
        String mchSecret = "kysmQ6zGeendZIiKKGK1lBT"; //商户密钥

        String productCode = "223";
        productCode=orderInfoMapper.getPayChannel();

        /**** 必填参数 ****/
        //<必填>商户订单号，由商户系统生成，必须保证唯一
        String mchOrderNo = orderInfo.getOrderNo();
        //<必填>商户用户id
        String mchUserId = "user_0001";
        //<必填>交易金额；单位：分
        Integer amount = orderInfo.getTotalFee().multiply(new BigDecimal("100")).intValue();
        //<必填>随机字符串；长度：8 ~ 32 个字符
        String nonce = MD5Util.MD5(String.valueOf(new Random().nextLong()));
        //<必填>时间戳
        Long timestamp = System.currentTimeMillis();
        //<必填>支付结果回调地址
        String notifyUrl = "https://www.53lmc.com/api/ali-pay/trade/notify2";

        /**** 非必填参数 ****/
        //<非必填>用户ip
        String userIp = "";
        //<非必填>支付成功跳转地址
        String returnUrl = "https://www.53lmc.com/#/success";
        //<非必填>用户姓名
        String userName = "";
        //<非必填>用户姓
        String userFirstName = "";
        //<非必填>用户名
        String userLastName = "";
        //<非必填>用户手机号
        String mobile = param.getPhone();
        //<非必填>用户邮箱
        String email = "";
        //<非必填>透传值，订单回调时原样返回
        String attach = param.getBxm_id();
        //<非必填>订单备注
        String remark = "购买权益卡";

        Map<String, Object> params = new HashMap<>(64);
        params.put("mchKey", mchKey);
        params.put("product", productCode);
        params.put("mchOrderNo", mchOrderNo);
        params.put("mchUserId", mchUserId);
        params.put("amount", amount);
        params.put("nonce", nonce);
        params.put("timestamp", timestamp);
        params.put("notifyUrl", notifyUrl);
        params.put("returnUrl", returnUrl);
        params.put("userIp", userIp);
        params.put("userName", userName);
        params.put("userFirstName", userFirstName);
        params.put("userLastName", userLastName);
        params.put("mobile", mobile);
        params.put("email", email);
        params.put("attach", attach);
        params.put("remark", remark);

        try {
            String needSignParamStr = YSPay.getNeedSignParamString(params, mchSecret);
            System.out.println("要验签的参数: " + needSignParamStr);
            // out>> amount=20000&attach=name=test&email=zhangsan@gmail.com&mchKey=10008&mchOrderNo=order000000000002&mchUserId=user_0001&mobile=18888888888&nonce=10ff070de3adcee3607b967fbb44a3a5&notifyUrl=http://www.xxx.com/notify/url&product=wechat-h5&remark=会员充值订单&returnUrl=http://www.xxxx.com/api/order/success&timestamp=1637304432867&userFirstName=zhang&userIp=234.121.134.32&userLastName=san&userName=zhangsankys-iYuCXJG3OV-M5sJxUPVH6

            String sign = MD5Util.MD5(needSignParamStr);
            System.out.println("生成参数签名: " + sign);
            // out>> f0c9ab6e9c58cff76511ca26344b1208

            params.put("sign", sign);
//            System.out.println("请求参数: " + params);
            log.info("ys支付请求参数: {}", JSONObject.toJSONString(params));
            //out>> {mchOrderNo=order000000000002, sign=f0c9ab6e9c58cff76511ca26344b1208, remark=会员充值订单, mchKey=10008, attach=name=test, returnUrl=http://www.xxxx.com/api/order/success, email=zhangsan@gmail.com, timestamp=1637304432867, product=wechat-h5, amount=20000, mobile=18888888888, userName=zhangsan, userFirstName=zhang, userLastName=san, nonce=10ff070de3adcee3607b967fbb44a3a5, mchUserId=user_0001, notifyUrl=http://www.xxx.com/notify/url, userIp=234.121.134.32}

            String response = YSPay.doPost(payGateWay, params, new HashMap<>());
//            System.out.println("响应结果：" + response);
            log.info("ys支付响应结果: {}", response);
            return response;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
}
